perm filename RECOG1.SAI[SYS,HE]1 blob sn#016494 filedate 1972-12-06 generic text, type T, neo UTF8
COMMENT ⊗   VALID 00018 PAGES 
RECORD PAGE   DESCRIPTION
 00001 00001
 00005 00002	ENTRY DUMMY
 00006 00003	α	GENSYM
 00007 00004	α	TABCOOR
 00008 00005	α	DET3X3
 00009 00006	α	INVERT
 00010 00007	α	HOMO_XFRM
 00011 00008	α	BESTIN
 00013 00009	α	INITIALIZE
 00014 00010	α	MATMULT
 00015 00011	α	VERT_LINE_PT
 00017 00012	α	ANGLE
 00019 00013	α	DIST
 00020 00014	α	VERT
 00021 00015	α	PARALLEL
 00022 00016	α	COLINEAR
 00026 00017	α	CROSS_PROD
 00027 00018	α	DOT_PROD
 00028 ENDMK
⊗;
ENTRY DUMMY;

BEGIN "RECOG1.SAI"

REQUIRE		250	PNAMES;
REQUIRE "PREAMB.SAI[SYS,HE]"	SOURCE_FILE;
REQUIRE	"SYMBOL.AUX[H,RPO]"	SOURCE_FILE;
REQUIRE	"RECCOM.AUX[SYS,HE]"	SOURCE_FILE;

α LOCALS;
INTEGER FLAG,ERRFLAG;

α EXTERNAL PROCEDURES;
ERP		ACOS(REAL X);
ERP		ATAN(REAL X);
ERP		SQRT(REAL X);
ESP		PRINTNAME(ITEMVAR X);

α	GENSYM;

INTERNAL STRING PROCEDURE GENSYM(INTEGER ITEMVAR X);
BEGIN "GENSYM"
	STRING NAME;
	NAME←PRINTNAME(X);
	IF FLAG
	THEN BEGIN
		TYPE "GENSYM - PRINTNAME LOSSAGE" EOM;
		CALL(0,"EXIT");
		END;
	RETURN(NAME&CVS(∂(X)←∂(X)+1));
	END "GENSYM";

α	TABCOOR
the image coordinate system has been flipped right side up,
ergo the SDY hack in line .+10
;
EXTERNAL REAL SDY;

INTERNAL PROCEDURE TABCOOR(SAFE REAL ARRAY ITEMVAR U);
BEGIN "TABCOOR"
INTEGER I;
	FOR I←1 S1U 3 DO
	BEGIN
		∂(U)[I+2]←0.0;
		∂(U)[I+2]←∂(U)[I+2]+∂(U)[1]*AI_REC[I,1]
		+(SDY-∂(U)[2])*AI_REC[I,2]+AI_REC[I,3];
		END;
	FOR I←3 S1U 5 DO
		∂(U)[I]←∂(U)[I]/∂(U)[5];
	∂(U)[5]←0.0;
	END "TABCOOR";

α	DET3X3;

INTERNAL REAL PROCEDURE DET3X3(REAL ARRAY A);
BEGIN "DET3X3"
	  REAL V;
	  V←0.0;
	  V←V+(A[1,1]*A[2,2]*A[3,3]);
	  V←V+(A[1,2]*A[2,3]*A[3,1]);
	  V←V+(A[1,3]*A[3,2]*A[2,1]);
	  V←V-(A[3,1]*A[2,2]*A[1,3]);
	  V←V-(A[3,2]*A[2,3]*A[1,1]);
	  V←V-(A[3,3]*A[1,2]*A[2,1]);

	  RETURN (V);
       END "DET3X3";

α	INVERT;

INTERNAL PROCEDURE INVERT(REAL ARRAY A, AI);
BEGIN "INVERT"
	  REAL ARRAY B[1:3,1:3],ADJA[1:4,1:4];
	  INTEGER I,J,K,L,M,N; REAL DET;

	  FOR I←1 S1U 4 DO
	   FOR J←1 S1U 4 DO
	    BEGIN
	       M←N←1;
	       FOR K←1 S1U 4 DO
		FOR L←1 S1U 4 DO
		 IF K≠I ∧ L≠J THEN
		  BEGIN
		     B[M,N]←A[K,L];
		     N←(N+1) MOD 4;
		     IF N=0 THEN BEGIN
			N←N+1; M←(M+1) MOD 4;
		     END;
		  END;
	       ADJA[I,J]←((-1)↑(I+J))*DET3X3(B);
	    END;
	  DET←ADJA[4,4];
	  FOR I←1 S1U 4 DO
	   FOR J←1 S1U 4 DO
	    AI[I,J]←ADJA[J,I]/DET;

	  RETURN;
       END "INVERT";


α	HOMO_XFRM
transform P by the 4X4 homogeneous transformation matrix T
;

INTERNAL PROCEDURE HOMO_XFRM(SAFE REAL ARRAY P,T);
BEGIN "HOMO_XFRM"
	  SAFE REAL ARRAY TEMP[1:4];
	  INTEGER I,J;
	  FOR I←1 S1U 4 DO
	   BEGIN
	      TEMP[I]←0.0;
	      FOR J←1 S1U 4 DO
	       TEMP[I]←TEMP[I]+T[I,J]*P[J];
	   END;
	  FOR J←1 S1U 4 DO P[J]←TEMP[J]/TEMP[4];
       END "HOMO_XFRM";

α	BESTIN
finds the "best intersection" of 2 skew lines
;

INTERNAL PROCEDURE BESTIN(SAFE REAL ARRAY PJ,QJ,PK,QK,INT;
	REFERENCE REAL MISDIS);
BEGIN "BESTIN"
	  SAFE REAL ARRAY VJ[1:3],VK[1:3],DIS[1:3],PD[1:3];
	  REAL A,B,C,D,E,DET,TJ,TK; INTEGER I;
	  A←B←C←D←E←MISDIS←0;

	  FOR I←1 STEP 1 UNTIL 3 DO
	   BEGIN
	      PD[I]←PK[I]-PJ[I];
	      VJ[I]←QJ[I]-PJ[I];
	      VK[I]←QK[I]-PK[I];

	      A←A+VJ[I]↑2;
	      B←B-VJ[I]*VK[I];
	      C←C+VK[I]↑2;
	      D←D+PD[I]*VJ[I];
	      E←E-PD[I]*VK[I];
	   END;

	  DET←A*C-B↑2;
	  TJ←(C*D-B*E)/DET;
	  TK←(A*E-B*D)/DET;
	  FOR I←1 STEP 1 UNTIL 3 DO
	   BEGIN
	      INT[I]←(PJ[I]+PK[I]+TK*VK[I]+TJ*VJ[I])/2;
	      DIS[I]←TJ*VJ[I]-TK*VK[I]-PD[I];
	      MISDIS←MISDIS+DIS[I]↑2;
	   END;
	  MISDIS←SQRT(MISDIS);
	  RETURN;
       END "BESTIN";

α	INITIALIZE
initializes a 4X4 matrix to the identity matrix
;

INTERNAL PROCEDURE INITIALIZE(SAFE REAL ARRAY A);
BEGIN "INITIALIZE"
	  INTEGER I,J;
	  FOR I←1 STEP 1 UNTIL 4 DO
	   FOR J←1 STEP 1 UNTIL 4 DO
	    IF I=J THEN A[I,J]←1.0 ELSE A[I,J]←0.0;
	  RETURN ;
       END "INITIALIZE";

α	MATMULT
multiplies 2 nXn matrices
;

INTERNAL PROCEDURE MATMULT(SAFE REAL ARRAY A,B,C;INTEGER N);
BEGIN "MATMULT"
	  INTEGER I,J,K; REAL SUM;
	  SAFE REAL ARRAY D[1:N,1:N];

	  FOR I←1 STEP 1 UNTIL N DO
	   FOR J←1 STEP 1 UNTIL N DO
	    BEGIN
	       SUM←0.0;
	       FOR K←1 STEP 1 UNTIL N DO
		SUM←SUM+A[I,K]*B[K,J];
	       D[I,J]←SUM;
	    END;
	  FOR I←1 STEP 1 UNTIL N DO
	   FOR J←1 STEP 1 UNTIL N DO
	    C[I,J]←D[I,J];

	  RETURN;

       END "MATMULT";


α	VERT_LINE_PT
T is top and B is bottom image vertex assumed to lie
on a line normal to the table plane.
Returns with the true 3-d coords stuffed into T.
;

INTERNAL PROCEDURE VERT_LINE_PT(SAFE REAL ARRAY ITEMVAR T,B);
BEGIN "VERT_LINE_PT"
	  SAFE REAL ARRAY TOP,INT,P,BASE[1:3];
	  INTEGER I;REAL MISDIS;

	TYPE "VERT_LINE_PT - ENTERED" EOM;
	  FOR I←1 S1U 2 DO
	   BEGIN
	      TOP[I]←∂(T)[I+2];
	      P[I]←BASE[I]←∂(B)[I+2];
	   END;
	  TOP[3]←BASE[3]←∂(B)[5];
	  P[3]←∂(B)[5]+1.0;

	  TYPE TAB&"TOP "&CVG(TOP[1])&"  "&CVG(TOP[2])&"  "&CVG(TOP[3]) EOM;
	  TYPE TAB&"LENS_REC "&CVG(LENS_REC[1])&"  "&CVG(LENS_REC[2])&"  "&
	   CVG(LENS_REC[3]) EOM;
	  TYPE TAB&"BASE "&CVG(BASE[1])&"  "&CVG(BASE[2])&"  "&CVG(BASE[3])
	   EOM;
	  TYPE TAB&"P "&CVG(P[1])&"  "&CVG(P[2])&"  "&CVG(P[3]) EOM;

	  BESTIN(TOP,LENS_REC,BASE,P,INT,MISDIS);
	  TYPE TAB&"VLP "&PRINTNAME(T)&"  "&PRINTNAME(B)&CVG(INT[3]) EOM;
	  FOR I← 1 S1U 3 DO
	   ∂(T)[I+2]←INT[I];
	  RETURN;
       END "VERT_LINE_PT";

α	ANGLE
returns the angle in degrees of the angle formed by P1,P2,P3.
DIMS is the number of dimensions of the point.;

INTERNAL REAL PROCEDURE ANGLE(SAFE REAL ARRAY ITEMVAR P1,P2,P3;
	INTEGER DIMS);
BEGIN "ANGLE"
	  SAFE REAL ARRAY V1,V2[1:3];
	  INTEGER I;REAL MSV1,MSV2,X,DOT;

	  DOT←MSV1←MSV2←0.0;

	  IF DIMS=3 THEN

	   FOR I←1 S1U 3 DO
	    BEGIN
	       V1[I]←∂(P1)[I+2]-∂(P2)[I+2];
	       V2[I]←∂(P3)[I+2]-∂(P2)[I+2];
	       DOT←DOT+V1[I]*V2[I];
	       MSV1←MSV1+V1[I]↑2;
	       MSV2←MSV2+V2[I]↑2;
	    END

	    ELSE IF DIMS=2 THEN

	     FOR I←1 S1U 2 DO
	      BEGIN
		 V1[I]←∂(P1)[I]-∂(P2)[I];
		 V2[I]←∂(P3)[I]-∂(P2)[I];
		 DOT←DOT+V1[I]*V2[I];
		 MSV1←MSV1+V1[I]↑2;
		 MSV2←MSV2+V2[I]↑2;
	      END

	      ELSE IF DIMS=4 THEN

	       FOR I←1 S1U 3 DO
		BEGIN
		   V1[I]←GLB ∂(P1)[I]-GLB ∂(P2)[I];
		   V2[I]←GLB ∂(P3)[I]-GLB ∂(P2)[I];
		   DOT←DOT+V1[I]*V2[I];
		   MSV1←MSV1+V1[I]↑2;
		   MSV2←MSV2+V2[I]↑2;
		END

		ELSE TYPE "ANGLE - WRONG NUMBER OF DIMENSIONS"
		 EOM;
	  X←DOT/SQRT(MSV1*MSV2);
	  X←57.3*ACOS(X);
	  RETURN(X);
       END "ANGLE";

α	DIST
returns the image distance between two points in raster units.
;

INTERNAL REAL PROCEDURE DIST(SAFE REAL ARRAY ITEMVAR P1,P2);
BEGIN "DIST"
	REAL X;
	X←SQRT((∂(P1)[1]-∂(P2)[1])↑2+(∂(P1)[2]-∂(P2)[2])↑2);
	RETURN (X);
	END "DIST";


α	VERT
Is edge E approximately vertical in the projection?;

INTERNAL BOOLEAN PROCEDURE VERT(ITEMVAR E);
BEGIN "VERT"
	SAFE REAL ARRAY ITEMVAR P1,P2;
	SET ES;
	REAL A,B,C,D,VERTES;

ES←(ENDPT⊗E);
P1←LOP(ES);
P2←COP(ES);

	A←∂(P2)[2]-∂(P1)[2];
	B←∂(P1)[1]-∂(P2)[1];
	D←SQRT(A↑2 + B↑2);
	A←A/D;
	B←B/D;
	VERTES←ABS(A+B);

	IF .900 < VERTES < 1.100
	THEN BEGIN
		TYPE "VERT - "&PRINTNAME(E)&" (T "&CVG(VERTES)&")" EOM;
		RETURN (TRUE);
		END
	ELSE BEGIN
		TYPE "VERT - "&PRINTNAME(E)&" (F "&CVG(VERTES)&")" EOM;
		RETURN (FALSE);
		END;
END "VERT";
α	PARALLEL
returns true if 2 lines are parallel in the projection.;

INTERNAL BOOLEAN PROCEDURE PARALLEL(ITEMVAR L1,L2);
BEGIN "PARALLEL"
	SET S;
	SAFE REAL ARRAY ITEMVAR X,Y,Z,W;
	REAL SLOPE1,SLOPE2;

	IF VERT(L1) ∧ VERT(L2)
	THEN RETURN (TRUE);

	S←ENDPT⊗L1;
	X←LOP(S);
	Y←COP(S);
	S←ENDPT⊗L2;
	Z←LOP(S);
	W←COP(S);


	S←PHI;
	SLOPE1←(∂(X)[2]-∂(Y)[2])/(∂(X)[1]-∂(Y)[1]);
	SLOPE2←(∂(Z)[2]-∂(W)[2])/(∂(Z)[1]-∂(W)[1]);

	IF 57.3*ABS(ATAN(SLOPE1)-ATAN(SLOPE2))<PARAL1
	THEN RETURN (TRUE)
	ELSE RETURN (FALSE);

	END "PARALLEL";


α	COLINEAR
determines if two lines are colinear by measuring
the error of the inner endpoints from the line defined by 
the outer endpoints of U and V.
;

INTERNAL BOOLEAN PROCEDURE COLINEAR(ITEMVAR U,V);
BEGIN "COLINEAR"
      SET S;
      SAFE REAL ARRAY ITEMVAR X,Y,W,Z,PU,PV;
      REAL A,B,C,D,DIST1,DIST2,UDIST,VDIST,TDIST,ERROR,UERROR,VERROR;
      DEFINE
		XX(Z)=<∂(Z)[1]>,
		YY(Z)=<∂(Z)[2]>,
		EQUATION(Z)=<ABS(A*XX(Z) + B*YY(Z) +C)>;

TYPE "COLINEAR - "&PRINTNAME(U)&","&PRINTNAME(V) EOM;

      S←(ENDPT⊗U);
      X←LOP(S);
      Y←COP(S);
      DIST1←DIST(X,Y);
      S←(ENDPT⊗V);
      Z←LOP(S);
      W←COP(S);
      DIST2←DIST(Z,W);
      S←PHI;
      IF DIST2>DIST1
       THEN BEGIN
	  X↔Z;
	  Y↔W;
       END;
      IF DIST(Z,X)<DIST(W,X)
       THEN Z↔W;
      IF DIST(X,W)<DIST(Y,W)
       THEN X↔Y;
      PU←X; PV←Z;

α ARE LINES TOO SMALL WRT CAMERA GRID ??;
      IF ABS(∂(X)[1]-∂(Y)[1])<2.0
       THEN IF	ABS(∂(Z)[1]-∂(W)[1])<2.0 ∧
	ABS(∂(Z)[1]-∂(X)[1])<5.0
	 THEN BEGIN TYPE TAB&"(SMALL) TRUE" EOM; RETURN (TRUE); END
	  ELSE BEGIN TYPE TAB&"(SMALL) FALSE" EOM;RETURN (FALSE); END;

IF ¬PARALLEL(U,V)
THEN BEGIN
	TYPE TAB&"(¬PARALLEL) FALSE" EOM;
	RETURN (FALSE);
	END;


      α NOW GET THE SLOPE AND EQUATION OF LINE PU→PV
	A*X+B*Y+C=0	WHERE A,B ARE NORMALIZED COEFFICIENTS,
	I.E. A←DELTA Y, B←-DELTA X, D←SQRT(A↑2 + B↑2), A←A/D, B←B/D;


	A←YY(PU)-YY(PV);
	B←XX(PV)-XX(PU);
	D←SQRT(A↑2 + B↑2);
	A←A/D;
	B←B/D;
	C← - A*XX(PU) - B*YY(PU);

      UDIST←DIST(X,Y);
      VDIST←DIST(W,Z);
      TDIST←UDIST+VDIST;
      UERROR←EQUATION(Y);
      VERROR←EQUATION(W);
      ERROR←.25*TDIST/2;

α TYPEOUT SHOULD SHOW VALUES ≤ 1.0 FOR BOTH;

IF UERROR≤ERROR ∧ VERROR≤ERROR
THEN BEGIN
	TYPE TAB&"("&CVG(UERROR/ERROR)&","&CVG(VERROR/ERROR)&") TRUE" EOM;
	RETURN(TRUE);
	END
ELSE BEGIN
	TYPE TAB&"FALSE" EOM;
	RETURN(FALSE);
	END;
END "COLINEAR";

α	CROSS_PROD
returns AXB in CP;

INTERNAL PROCEDURE CROSS_PROD(REFERENCE SAFE REAL ARRAY A,B,CP);
BEGIN "CROSS_PROD"
	  CP[1]←A[2]*B[3]-A[3]*B[2];
	  CP[2]←A[3]*B[1]-A[1]*B[3];
	  CP[3]←A[1]*B[2]-A[2]*B[1];
	  RETURN;
       END "CROSS_PROD";

α	DOT_PROD
value is the dot product of vectors V1 and V2.;

INTERNAL REAL PROCEDURE DOT_PROD(SAFE REAL ARRAY V1,V2);
BEGIN "DOT_PROD"
	  REAL DP; INTEGER I;
	  DP←0.0;
	  FOR I←1 STEP 1 UNTIL 3 DO
	   DP←DP+V1[I]*V2[I];
	  RETURN (DP);
       END "DOT_PROD";

END "RECOG1.SAI";